﻿using System;
using System.Collections.Generic;
using GameFramework.Battle.Core;
using Gameplay.PVE.Utils;
using RootMotion.FinalIK;
using UnityEngine;
using Yoozoo.Managers;
using Random = System.Random;

namespace Gameplay.PVE.Survivor
{
    public class NormalAttackComponent: ComponentBase
    {
        private SkillConfig config;
        private NormalAttackSkill skill;
        private List<NormalAttackSkill> skillPool;
        private float reloadStartTime;
        private float normalAttackCDTime;
        
        public float attackRange => config?.cast_range ?? 0;

        private float nextCdTime;
        
        protected override void OnInitialized()
        {
            if (unit.config.attack_id == 0)
            {
                return;
            }
            var config = BattleConfigManager.Instance.GetSkillConfig(unit.config.attack_id);
            if (config.type == (int)EBattleSkillType.RandomSkill)
            {
                skillPool = new List<NormalAttackSkill>();
                for (int i = 0; i < config.value.Count; i++)
                {
                    var skillId = config.value[i];
                    var skillConfig = BattleConfigManager.Instance.GetSkillConfig(skillId);
                    var skill = ClassManager.Get<NormalAttackSkill>();
                    skill.groupSkillId = config.id;
                    skill.Initialize(skillConfig, unit);
                    skillPool.Add(skill);
                }
                GetSkill();
            }
            else
            {
                this.config = config;
                skill = ClassManager.Get<NormalAttackSkill>();
                skill.groupSkillId = config.id;
                skill.Initialize(config, unit);
                skill.ammoCount = config.ammo_count;
            }
        }
        
        private void GetSkill()
        {
            var index = UnityEngine.Random.Range(0, skillPool.Count);
            skill = skillPool[index];
            config = skill.config;
        }

        protected override void OnUpdate()
        {
            if (skill == null)
            {
                return;
            }
            var needCheckAttackState = false;
            var changeReason = 0;
            if (reloadStartTime > 0)
            {
                if (TimeManager.time - reloadStartTime >= config.reload_time)
                {
                    needCheckAttackState = true;
                    changeReason = 1;
                    reloadStartTime = 0;
                    unit.consumedAmmoCount = 0;
                }
            }

            if (normalAttackCDTime > 0)
            {
                if (TimeManager.time > normalAttackCDTime)
                {
                    normalAttackCDTime = 0;
                    needCheckAttackState = true;
                    changeReason = 2;
                }
            }

            if (skill != null && skill.JustEnd())
            {
                skill.Reset();
                needCheckAttackState = true;
                changeReason = 3;
                //敌方每次索敌完成后更换目标
                if (unit.team == 2)
                {
                    unit.SearchTarget();
                }
            }

            if (needCheckAttackState)
            {
                //if (unit.HasTarget() &&unit.IsTargetInRange())
                if (!unit.IsReloading() && !unit.IsInSkill() && !unit.isDead && !unit.IsInControl())
                {
                    //BattleDebug.Log(unit.unitId + " NormalAttack Changed " + changeReason);
                    unit.Play("Idle",false,false);
                }
                /*else
                {
                    unit.Play("Idle");
                    unit.EndAim();
                }*/
            }
            else
            {
                if (unit.isAiming && (!unit.HasTarget() && !unit.HasTeamTarget() && !unit.IsInSkill()))
                {
                    StopNormalAttack();
                    unit.Play("Idle");
                    unit.EndAim();
                }
            }
        }

        public override void LateUpdate()
        {
            skill?.LateUpdate();
        }

        public bool IsAmmoEmpty()
        {
            if (config == null || skill == null)
            {
                return false;
            }
            return config.reload_time > 0 && unit.consumedAmmoCount >= skill.ammoCount;
        }

        public bool CanNormalAttack()
        {
            return skill != null && (nextCdTime == 0 || TimeManager.time > skill.skillEndTime + nextCdTime);
        }

        public void NormalAttackCD()
        {
            if (normalAttackCDTime == 0 && skill != null)
            {
                normalAttackCDTime = skill.skillEndTime + nextCdTime;
            }
        }
        
        public void StartNormalAttack(BattleUnit target)
        {
            if (skillPool != null)
            {
                GetSkill();
            }

            if (skill == null)
            {
                return;
            }
            skill.SetTarget(target);
            skill.Start();
            if (skill.NeedSpecialAim())
            {
                unit.TargetForward = target.Position - unit.Position;
            } 
            else if(skill.NeedAim())
            {
                unit.StartAim();
            }
            else
            {
                unit.TargetForward = target.Position - unit.Position;
                unit.EndAim();
            }
            normalAttackCDTime = 0;
            nextCdTime = UnityEngine.Random.Range(config.shoot_interval[0],config.shoot_interval[1]);
        }

        public void StopNormalAttack()
        {
            skill?.End();
        }
        
        public void UpdateNormalAttack()
        {
            skill?.Update();
        }

        public bool IsInSkill()
        {
            if (skill == null)
            {
                return false;
            }
            return skill.IsInSkill();
        }

        public bool IsReloading()
        {
            return reloadStartTime > 0;
        }

        public void Reload()
        {
            skill?.End();
            reloadStartTime = TimeManager.time;
            unit.Play("Reload");
            nextCdTime = 0;
        }

        protected override void OnDead()
        {
            base.OnDead();
            skill?.End();
        }
        
        public override void OnReset()
        {
            base.OnReset();
            reloadStartTime = 0;
            normalAttackCDTime = 0;
            nextCdTime = 0;
            if (skillPool != null)
            {
                for (int i = 0; i < skillPool.Count; i++)
                {
                    var skill = skillPool[i];
                    skill.End();
                    ClassManager.Free(skill);   
                }
                skillPool.Clear();
                skillPool = null;
            }
            else
            {
                if (skill != null)
                {
                    skill.End();
                    ClassManager.Free(skill);
                    skill = null;
                }
            }
        }
    }
}
